package com.mall.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mall.entity.sys.ResEO;
import com.mall.utils.SysPasswordEncoder;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

//@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

   @Override
   protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.inMemoryAuthentication().passwordEncoder(new SysPasswordEncoder()).withUser("test").password("1").roles("user");
   }

   @Override
   public void configure(WebSecurity web) throws Exception {
   }

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests()//
            .anyRequest().authenticated()//
              .antMatchers("/sys/login").permitAll()//

            .and().formLogin().loginProcessingUrl("/json/login")//

            .successHandler(new AuthSuccessHandler())//
            .failureHandler(new AuthFailureHandler())//

            .permitAll()//

            .and().logout().logoutUrl("/json/logout")//

            .logoutSuccessHandler(new AuthLogoutSuccessHandler())//

            .permitAll()//

            .and().exceptionHandling().accessDeniedHandler(new AuthAccessDeniedHandler())//

            .and().csrf().disable()//
      ;
   }
}

class AuthSuccessHandler implements AuthenticationSuccessHandler {
   @Override
   public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
      ResEO res = ResEO.success("登录成功！", authentication.getPrincipal());
      resp.setContentType("application/json;charset=utf-8");
      PrintWriter out = resp.getWriter();
      out.write(new ObjectMapper().writeValueAsString(res));
      out.flush();
      out.close();
   }
}

class AuthFailureHandler implements AuthenticationFailureHandler {
   @Override
   public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {
      ResEO error = ResEO.error("登录失败");
      resp.setContentType("application/json;charset=utf-8");
      PrintWriter out = resp.getWriter();
      out.write(new ObjectMapper().writeValueAsString(error));
      out.flush();
      out.close();
   }
}

class AuthLogoutSuccessHandler implements LogoutSuccessHandler {
   @Override
   public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
      ResEO res = ResEO.success("注销成功！");
      resp.setContentType("application/json;charset=utf-8");
      PrintWriter out = resp.getWriter();
      out.write(new ObjectMapper().writeValueAsString(res));
      out.flush();
      out.close();
   }
}

class AuthAccessDeniedHandler implements AccessDeniedHandler {
   @Override
   public void handle(HttpServletRequest req, HttpServletResponse resp, AccessDeniedException e) throws IOException, ServletException {
      ResEO error = ResEO.error("权限不足，访问失败");
      resp.setStatus(403);
      resp.setContentType("application/json;charset=utf-8");
      PrintWriter out = resp.getWriter();
      out.write(new ObjectMapper().writeValueAsString(error));
      out.flush();
      out.close();
   }
}
